from django.shortcuts import render
# 导入数据模型ArticlePost
from .models import ArticlePost

# 引入分页模块
from django.core.paginator import Paginator
import markdown
import re
from lxml import etree

# 引入 Q 对象
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from flow_statistics.utils import statistic_decorator, statistic_view_count
from comment.models import Comment


def article_list(request):
    statistic_view_count(request)
    # 从 url 中提取查询参数
    search = request.GET.get('search')
    order = request.GET.get('order')
    column = request.GET.get('column')
    tag = request.GET.get('tag')

    # 初始化查询集
    article_list = ArticlePost.objects.all()
    if article_list.count():
        print(' ======== ======== ======== article_list[0].author: ', article_list[0].author)
        print(' ====== ======== ========== article_list[0].author_id: ', article_list[0].author_id)
    # 搜索查询集
    if search:
        article_list = article_list.filter(
            Q(title__icontains=search)
            | Q(body__icontains=search)
            | Q(author__username=search)
        )
    else:
        search = ''

    # 栏目查询集
    if column is not None and column.isdigit():
        article_list = article_list.filter(column=column)

    # 标签查询集
    if tag and tag != 'None':
        article_list = article_list.filter(tags__name__in=[tag])

    # 查询集排序
    if order == 'total_views':
        article_list = article_list.order_by('-total_views')

    paginator = Paginator(article_list, 3)
    page = request.GET.get('page')
    articles = paginator.get_page(page)

    # get_article_abstract
    if(1):
        def get_article_abstract(article):
            html = markdown.markdown(article.body)
            content = etree.HTML(html)
            pure_text = content.xpath('string()')  # 减去 链接 | 图片 | 资源 后的 纯文本.


            reg = re.compile(r'<.*?>')  # 去掉标签
            pure_text = reg.sub('', pure_text)

            reg = re.compile(r'`{3}.*`{3}', re.S)  # 去掉标签
            pure_text = reg.sub('<**代码块**>', pure_text)

            # reg = re.compile(r'\n', re.S)  # 加入换行失败, 以后研究.
            # pure_text = reg.sub('<br>', pure_text)

            # print(pure_text[:100])

            # pure_text = markdown.markdown(pure_text)
            abstract = pure_text
            return abstract


        for article in articles:
            article.abstract = get_article_abstract(article)

    # 需要传递给模板（templates）的对象
    context = {
        'articles': articles,
        'order': order,
        'search': search,
        'column': column,
        'tag': tag,
    }

    return render(request, 'article/list.html', context)


def article_detail(request, id):
    article = ArticlePost.objects.get(id=id)
    # 将markdown语法渲染成html样式
    article.body = markdown.markdown(article.body,
        extensions=[
        # 包含 缩写、表格等常用扩展
        'markdown.extensions.extra',
        # 语法高亮扩展
        'markdown.extensions.codehilite',
        ])
    article_post_form = ArticlePostForm()
    columns = ArticleColumn.objects.all()

    # 取出文章评论
    comments = Comment.objects.filter(article=id)

    context = {
        'article': article,
        'article_post_form': article_post_form,
        'columns': columns,
        # 'toc': md.toc,
        'comments': comments
    }
    # context = { 'article': article }
    return render(request, 'article/detail.html', context)

# -------------- forms

# 引入redirect重定向模块
from django.shortcuts import render, redirect
# 引入HttpResponse
from django.http import HttpResponse
# 引入刚才定义的ArticlePostForm表单类
from .forms import ArticlePostForm
# 引入User模型
from django.contrib.auth.models import User

# 引入栏目Model
from .models import ArticleColumn

# 写文章的视图
@login_required(login_url='/userprofile/login/')
def article_create(request):
    # 获取需要修改的具体文章对象
    # article = ArticlePost.objects.get(id=id)

    # 过滤非作者的用户
    # if request.user != article.author:
    #     return HttpResponse("抱歉，你无权修改这篇文章。")

    # 判断用户是否提交数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        # article_post_form = ArticlePostForm(data=request.POST)

        # 增加 request.FILES
        article_post_form = ArticlePostForm(request.POST, request.FILES)

        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存数据，但暂时不提交到数据库中
            new_article = article_post_form.save(commit=False)
            # 指定数据库中 id=1 的用户为作者
            # 如果你进行过删除数据表的操作，可能会找不到id=1的用户
            # 此时请重新创建用户，并传入此用户的id
            print('------------------- 文章作者name为: ', request.user)
            # print('------------------- 文章作者id为: ', User.objects.get(name=request.user))

            # import time as tt
            # tt.sleep(3)
            new_article.author = request.user
            # new_article.author = User.objects.get(id=1)

            print('---------------- new_article.title: ', new_article.title)
            print('---------------- new_article.href: ', new_article.href)
            # 新增的代码
            if request.POST['column'] != 'none':
                new_article.column = ArticleColumn.objects.get(id=request.POST['column'])

            # 已有代码
            # 将新文章保存到数据库中
            new_article.save()

            # 新增代码，保存 tags 的多对多关系
            article_post_form.save_m2m()


            # 完成后返回到文章列表
            return redirect("article:article_list")
        # 如果数据不合法，返回错误信息
        else:
            return HttpResponse("表单内容有误，请重新填写。")
    # 如果用户请求获取数据
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()

        # 新增及修改的代码
        columns = ArticleColumn.objects.all()
        context = {'article_post_form': article_post_form, 'columns': columns}

        # 赋值上下文
        # context = { 'article_post_form': article_post_form }
        # 返回模板
        return render(request, 'article/create.html', context)


# 删文章
def article_delete(request, id):
    # 根据 id 获取需要删除的文章
    article = ArticlePost.objects.get(id=id)
    # 调用.delete()方法删除文章
    article.delete()
    # 完成删除后返回文章列表
    return redirect("article:article_list")


# 安全删除文章
def article_safe_delete(request, id):
    print('~~~~~~~ 安全删除文章')
    if request.method == 'POST':
        article = ArticlePost.objects.get(id=id)
        article.delete()
        return redirect("article:article_list")
    else:
        return HttpResponse("仅允许post请求")


# 更新文章
# 提醒用户登录
@login_required(login_url='/userprofile/login/')
def article_update(request, id):
    """
    更新文章的视图函数
    通过POST方法提交表单，更新titile、body字段
    GET方法进入初始表单页面
    id： 文章的 id
    """

    # 获取需要修改的具体文章对象
    article: ArticlePost = ArticlePost.objects.get(id=id)

    # 过滤非作者的用户
    if request.user != article.author:
        return HttpResponse("抱歉，你无权修改这篇文章。")

    # 判断用户是否为 POST 提交表单数据
    if request.method == "POST":
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存新写入的 title、body 数据并保存
            article.title = request.POST['title']
            article.body = request.POST['body']
            if 'avatar' in request.FILES:
                article.avatar = request.FILES["avatar"]
            # article_post_form
            # article.avatar

            # 新增的代码 栏目
            if request.POST['column'] != 'none':
                article.column = ArticleColumn.objects.get(id=request.POST['column'])
            else:
                article.column = None

            article.save()
            # 完成后返回到修改后的文章中。需传入文章的 id 值
            return redirect("article:article_detail", id=id)
        # 如果数据不合法，返回错误信息
        else:
            return HttpResponse("表单内容有误，请重新填写。")

    # 如果用户 GET 请求获取数据
    else:
        # 创建表单类实例
        article_post_form = ArticlePostForm()
        # 赋值上下文，将 article 文章对象也传递进去，以便提取旧的内容
        # context = { 'article': article, 'article_post_form': article_post_form }
        # 新增及修改的代码
        columns = ArticleColumn.objects.all()

        # 取出文章评论
        comments = Comment.objects.filter(article=id)

        context = {
            'article': article,
            'article_post_form': article_post_form,
            'columns': columns,
            # 'toc': md.toc,
            'comments': comments
        }
        # from django.forms import model_to_dict
        # print('--- model_to_dict: ', model_to_dict(article))

        # 将响应返回到模板中
        return render(request, 'article/update.html', context)


from django.views.generic.edit import CreateView


class ArticleCreateView(CreateView):
    model = ArticlePost

    fields = '__all__'
    # 或者只填写部分字段，比如：
    # fields = ['title', 'content']

    # article/create_by_class_view
    template_name = 'article/create_by_class_view.html'





# <editor-fold desc='类视图'>

# from django.views import View
#
# class ArticleListView(View):
#     """处理GET请求"""
#     def get(self, request):
#         articles = ArticlePost.objects.all()
#         context = {'articles': articles}
#         return render(request, 'article/list.html', context)
#

from django.views.generic import ListView

class ArticleListView(ListView):
    # 上下文的名称
    context_object_name = 'articles'
    # 查询集
    queryset = ArticlePost.objects.all()
    # 模板位置
    template_name = 'article/list.html'

article_list_example = ArticleListView.as_view()
# article_list = ArticleListView.as_view()
# </editor-fold>

# class MyArticleListView(ListView):
#     # 上下文的名称
#     context_object_name = 'articles'
#     # 查询集
#     queryset = ArticlePost.objects.all()
#     # 模板位置
#     template_name = 'article/list.html'
#
# article_list_example = ArticleListView.as_view()

@login_required(login_url='/userprofile/login/')
def my_article_list(request):
    # 获取需要修改的具体文章对象
    # article = ArticlePost.objects.get(id=id)
    print('~~~~~~~ user_name:', request.user)
    # 过滤非作者的用户
    # if request.user != article.author:
    #     return HttpResponse("抱歉，你无权修改这篇文章。")

    # user = request.user
    # 从 url 中提取查询参数
    search = request.GET.get('search')
    order = request.GET.get('order')
    column = request.GET.get('column')
    tag = request.GET.get('tag')

    search = request.user

    # 初始化查询集
    article_list = ArticlePost.objects.all()

    print(' ======== ======== ======== article_list[0].author: ', article_list[0].author)
    print(' ====== ======== ========== article_list[0].author_id: ', article_list[0].author_id)
    # 搜索查询集
    if search:
        article_list = article_list.filter(
            Q(author__username=search)
        )
    else:
        search = ''

    # 栏目查询集
    if column is not None and column.isdigit():
        article_list = article_list.filter(column=column)

    # 标签查询集
    if tag and tag != 'None':
        article_list = article_list.filter(tags__name__in=[tag])

    # 查询集排序
    if order == 'total_views':
        article_list = article_list.order_by('-total_views')

    paginator = Paginator(article_list, 3)
    page = request.GET.get('page')
    articles = paginator.get_page(page)

    # get_article_abstract
    if (1):
        def get_article_abstract(article):
            html = markdown.markdown(article.body)
            content = etree.HTML(html)
            pure_text = content.xpath('string()')  # 减去 链接 | 图片 | 资源 后的 纯文本.

            reg = re.compile(r'<.*?>')  # 去掉标签
            pure_text = reg.sub('', pure_text)

            reg = re.compile(r'`{3}.*`{3}', re.S)  # 去掉标签
            pure_text = reg.sub('<**代码块**>', pure_text)

            # reg = re.compile(r'\n', re.S)  # 加入换行失败, 以后研究.
            # pure_text = reg.sub('<br>', pure_text)

            # print(pure_text[:100])

            # pure_text = markdown.markdown(pure_text)
            abstract = pure_text
            return abstract

        for article in articles:
            article.abstract = get_article_abstract(article)

    # 需要传递给模板（templates）的对象
    context = {
        'articles': articles,
        'order': order,
        'search': search,
        'column': column,
        'tag': tag,
    }

    return render(request, 'article/my_article_list.html', context)




# from django.views.generic import DetailView
#
# class ArticleDetailView(DetailView):
#     queryset = ArticlePost.objects.all()
#     context_object_name = 'article'
#     template_name = 'article/detail.html'

